function z_list = pick_z_from_XZ_YZ_concat_rclick_batch(Ixz, Iyz, X_list, Y_list, bandWidth, varargin)
% 批量交互：对每对 (X_i, Y_i)，只显示拼接带状图（XZ带 + 分隔 + YZ带）
% 两条黄色竖线标各自带的中心列；右键设置 Z；水平线可拖拽；左键平移；滚轮缩放；
% Enter 确认并关闭当前窗口；最终仅返回 z_list（Nx1）
%
% Ixz: [Z,X]   （横=X，纵=Z）
% Iyz: [Z,Y]   （横=Y，纵=Z）
% X_list, Y_list: 各 N×1 或 1×N
% bandWidth: 带宽像素（默认 10）
%
% Name-Value:
%   'AutoInit'  true/false（默认 true）：初始 Z 取两带沿 Z 的强度峰值平均；false 则取中点
%
% 返回：
%   z_list: N×1，对应每对 (X_i,Y_i) 的交互选定 Z

    p = inputParser;
    p.addParameter('AutoInit', true, @(x)islogical(x) || isnumeric(x));
    p.parse(varargin{:});
    AutoInit = logical(p.Results.AutoInit);

    if nargin < 5 || isempty(bandWidth), bandWidth = 10; end
    bandWidth = sanitize_scalar(bandWidth, 'bandWidth');

    assert(isnumeric(Ixz) && ismatrix(Ixz), 'Ixz 必须为二维矩阵 [Z,X]');
    assert(isnumeric(Iyz) && ismatrix(Iyz), 'Iyz 必须为二维矩阵 [Z,Y]');

    X_list = X_list(:);
    Y_list = Y_list(:);
    assert(numel(X_list)==numel(Y_list), 'X_list 与 Y_list 长度必须一致');
    N = numel(X_list);

    [Zx, Xmax] = size(Ixz);
    [Zy, Ymax] = size(Iyz);
    assert(Zx==Zy, 'XZ 与 YZ 的 Z 尺寸不一致');
    ZN = Zx;

    z_list = nan(N,1);

    for i = 1:N
        X0 = sanitize_scalar(X_list(i), 'X0');
        Y0 = sanitize_scalar(Y_list(i), 'Y0');

        % —— 取带并拼接 —— 
        idxX    = centered_indices(X0, bandWidth, Xmax);
        idxY    = centered_indices(Y0, bandWidth, Ymax);
        sliceXZ = Ixz(:, idxX);     % [Z, bandWidth]
        sliceYZ = Iyz(:, idxY);     % [Z, bandWidth]
        sepW = 2;
        catImg = [normalize01(sliceXZ), zeros(ZN,sepW), normalize01(sliceYZ)];

        % —— 显示（axis fill）——
        fig = figure('Name', sprintf('(%d/%d) X=%.3g, Y=%.3g — 右键设Z，Enter确认', i, N, X0, Y0), ...
                     'NumberTitle','off');
        ax  = axes('Parent', fig); %#ok<LAXES>
        imshow(catImg, [], 'Parent', ax, 'InitialMagnification','fit'); axis(ax,'fill'); hold(ax,'on');

        % 两条黄色竖线（中心列）
        colL = ceil(bandWidth/2);
        colR = bandWidth + sepW + ceil(bandWidth/2);
        yl   = [1 ZN];
        line(ax, [colL colL], yl, 'Color','y', 'LineWidth',1.5);
        line(ax, [colR colR], yl, 'Color','y', 'LineWidth',1.5);

        % 初始水平线
        if AutoInit
            prof1 = sum(sliceXZ, 2);
            prof2 = sum(sliceYZ, 2);
            [~, p1] = max(prof1); [~, p2] = max(prof2);
            z0 = mean([p1, p2]);
        else
            z0 = (ZN+1)/2;
        end
        hHL = line(ax, [1 size(catImg,2)], [z0 z0], 'Color',[1 0 1], 'LineWidth', 1.6);
        makeHorizontalDraggable(ax, hHL, ZN);
        enablePanZoom(ax);

        % 右键设 Z；Enter 确认并关闭
        oldWBD = get(fig,'WindowButtonDownFcn');
        oldWKP = get(fig,'WindowKeyPressFcn');
        set(fig,'WindowButtonDownFcn', @(~,~) onRightClickSetZ(ax,hHL));
        set(fig,'WindowKeyPressFcn',   @(~,evt) onKeyConfirm(evt, fig));

        uiwait(fig);

        if ~isgraphics(hHL) || isempty(get(hHL,'YData'))
            z_list(i) = NaN;
        else
            ydat = get(hHL,'YData');
            z_list(i) = ydat(1);
        end

        % 恢复并关闭
        if isvalid(fig)
            try set(fig,'WindowButtonDownFcn',oldWBD); end
            try set(fig,'WindowKeyPressFcn',  oldWKP); end
            try close(fig); end
        end
    end
end

% ===== 工具函数 =====
function s = sanitize_scalar(v, name)
    if isempty(v), v = 1; end
    v = v(:); v = v(~isnan(v));
    if isempty(v), v = 1; end
    s = real(v(1));
end

function idx = centered_indices(c, w, Nmax)
    c = round(sanitize_scalar(c,'c'));
    w = max(1, round(sanitize_scalar(w,'w')));
    c = max(1, min(Nmax, c));
    left  = floor((w-1)/2);
    right = w-1-left;
    i1 = c-left;  i2 = c+right;
    if i1 < 1, d=1-i1; i1=1; i2=min(Nmax,i2+d); end
    if i2 > Nmax, d=i2-Nmax; i2=Nmax; i1=max(1,i1-d); end
    idx = i1:i2;
    if numel(idx) > w, idx = idx(1:w); end
    if numel(idx) < w
        need = w-numel(idx);
        i1b = max(1, i1-need);
        idx = i1b:(i1b+w-1);
        idx = max(1, min(Nmax, idx));
    end
end

function A = normalize01(A)
    A = double(A);
    A = A - min(A(:)); m = max(A(:));
    if m > 0, A = A./m; end
end

function onRightClickSetZ(ax, hHL)
    fig = ancestor(ax,'figure');
    if ~strcmpi(fig.SelectionType,'alt'), return; end  % 右键
    if ~isequal(ancestor(hittest(fig),'axes'), ax), return; end
    y = ax.CurrentPoint(1,2);
    set(hHL,'YData',[y y]);
end

function onKeyConfirm(evt, fig)
    if ismember(lower(evt.Key),{'return','enter'})
        try uiresume(fig); end
    end
end

function makeHorizontalDraggable(ax, hLine, ZN)
    fig = ancestor(ax,'figure');
    set(hLine,'ButtonDownFcn',@(src,~) startDrag(src));
    function startDrag(src)
        if ~strcmpi(fig.SelectionType,'normal'), return; end % 左键拖
        oldWBM = get(fig,'WindowButtonMotionFcn');
        oldWBU = get(fig,'WindowButtonUpFcn');
        set(fig,'WindowButtonMotionFcn',@(~,~) drag());
        set(fig,'WindowButtonUpFcn',    @(~,~) stopDrag());
        function drag()
            y = ax.CurrentPoint(1,2);
            y = max(1, min(ZN, y));
            set(src,'YData',[y y]);
        end
        function stopDrag()
            set(fig,'WindowButtonMotionFcn',oldWBM);
            set(fig,'WindowButtonUpFcn',oldWBU);
        end
    end
end

function enablePanZoom(ax)
    fig = ancestor(ax,'figure');
    isPan = false; last = [NaN NaN];
    oldWBM = get(fig,'WindowButtonMotionFcn');
    oldWBU = get(fig,'WindowButtonUpFcn');
    oldSWF = get(fig,'WindowScrollWheelFcn');

    set(fig,'WindowButtonDownFcn', @(~,~) onDown());
    set(fig,'WindowButtonMotionFcn',@(~,~) onMove());
    set(fig,'WindowButtonUpFcn',    @(~,~) onUp());
    set(fig,'WindowScrollWheelFcn', @(~,evt) onScroll(evt));

    function onDown()
        if ~isequal(ancestor(hittest(fig),'axes'), ax), return; end
        if ~strcmpi(fig.SelectionType,'normal'), return; end % 左键平移
        cp = ax.CurrentPoint(1,1:2);
        if inAx(cp), isPan = true; last = cp; end
    end
    function onMove()
        if ~isPan, return; end
        cp = ax.CurrentPoint(1,1:2); d = cp-last;
        xlim(ax, xlim(ax) - d(1));   % 横向=拼接列
        ylim(ax, ylim(ax) - d(2));   % 纵向=Z
        last = cp;
    end
    function onUp(), isPan = false; last = [NaN NaN]; end
    function onScroll(evt)
        cp = ax.CurrentPoint(1,1:2); if ~inAx(cp), return; end
        step = 1.10;
        s = (evt.VerticalScrollCount>0)*step + (evt.VerticalScrollCount<=0)*(1/step);
        xl = xlim(ax); yl = ylim(ax); cx=cp(1); cy=cp(2);
        newXL = cx + (xl - cx) * s; newYL = cy + (yl - cy) * s;
        if diff(newXL)>1e-6 && diff(newYL)>1e-6
            xlim(ax,newXL); ylim(ax,newYL);
        end
    end
    function tf = inAx(p)
        xl=xlim(ax); yl=ylim(ax);
        tf = p(1)>=min(xl)&&p(1)<=max(xl)&&p(2)>=min(yl)&&p(2)<=max(yl);
    end
end
